package com.linx.common.translation.aspect;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.linx.common.core.domain.R;
import com.linx.common.core.utils.StringUtils;
import com.linx.common.core.utils.reflect.ReflectUtils;
import com.linx.common.mybatis.core.page.TableDataInfo;
import com.linx.common.translation.annotation.TranslationBatch;
import com.linx.common.translation.annotation.TranslationSupper;
import com.linx.common.translation.core.TranslationInterface;
import com.linx.common.translation.core.handler.TranslationHandler;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.AutoConfiguration;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.CompletableFuture;

import static cn.hutool.core.lang.Singleton.put;

/**
 * 字段翻译处理
 *
 * @author Lion Li
 */
@Slf4j
@Aspect
@AutoConfiguration
public class TranslationAspect {

    @Around("@annotation(translationBatch)")
    public Object around(ProceedingJoinPoint joinPoint, TranslationBatch translationBatch) throws Throwable{
        //  异步线程队列
        List<CompletableFuture<Boolean>> futureList = new ArrayList<>();
        //  获取返回值
        Object jsonResult = joinPoint.proceed();

        //  处理非分页数据
        if (jsonResult instanceof R<?>) {
            R<Object> res = JSON.parseObject(JSON.toJSONString(jsonResult, SerializerFeature.WriteMapNullValue), new TypeReference<>() {});

            //  处理集合数据
            if (res.getData() instanceof List<?> || res.getData() instanceof Set<?>) {
                List<?> rowList = JSON.parseArray(JSON.toJSONString(res.getData(), SerializerFeature.WriteMapNullValue), translationBatch.resClass());

                for (Object row : rowList) {
                    translation(row, futureList);
                }

                //  等待异步线程结束
                for (CompletableFuture<Boolean> future : futureList) {
                    CompletableFuture.allOf(future).join();
                }

                // 重新设置data
                res.setData(rowList);
            }
            //  处理单个数据
            else {
                Object object = JSON.parseObject(JSON.toJSONString(res.getData(), SerializerFeature.WriteMapNullValue), translationBatch.resClass());
                translation(object, futureList);

                //  等待异步线程结束
                for (CompletableFuture<Boolean> future : futureList) {
                    CompletableFuture.allOf(future).join();
                }

                // 重新设置data
                res.setData(object);
            }

            return res;
        }

        //  处理分页数据
        if (jsonResult instanceof TableDataInfo) {
            TableDataInfo<Object> tableDataInfo = JSON.parseObject(JSON.toJSONString(jsonResult), new TypeReference<>() {});
            List rowList = JSON.parseArray(JSON.toJSONString(tableDataInfo.getRows(), SerializerFeature.WriteMapNullValue), translationBatch.resClass());
            for (Object row : rowList) {
                translation(row, futureList);
            }

            //  等待异步线程结束
            for (CompletableFuture<Boolean> future : futureList) {
                CompletableFuture.allOf(future).join();
            }

            // 重新设置rows
            tableDataInfo.setRows(rowList);

            return tableDataInfo;
        }

        return jsonResult;
    }

    /**
     * 翻译对象属性
     */
    private void translation(Object object, List<CompletableFuture<Boolean>> futureList) {
        for (Field field : object.getClass().getDeclaredFields()) {
            futureList.add(CompletableFuture.supplyAsync(() -> {
                field.setAccessible(true);  //  设置可以访问私有变量

                // 判断filed是否有final修饰符，如果有则不处理
                if (!Modifier.isFinal(field.getModifiers())) {
                    //  获取属性的注解，如果没有注解则不处理
                    TranslationSupper translationSupper = field.getAnnotation(TranslationSupper.class);
                    if (translationSupper != null) {
                        //  获取TranslationHandler中存储的翻译接口，在项目启动时已经加载
                        TranslationInterface<?> translationInterface = TranslationHandler.TRANSLATION_MAPPER.get(translationSupper.type());
                        if (ObjectUtil.isNotNull(translationInterface)) {
                            // 如果映射字段不为空 则取映射字段的值
                            if (StringUtils.isNotBlank(translationSupper.mapper())) {
                                // 取映射字段的值
                                Object mapperValue = ReflectUtils.invokeGetter(object, translationSupper.mapper());
                                Object mapper2Value = ReflectUtils.invokeGetter(object, translationSupper.mapper2());
                                if (ObjectUtil.isNotNull(mapperValue)) {
                                    Object translationValue = translationInterface.translation(mapperValue, mapper2Value, translationSupper.other(), translationSupper.clazz());
                                    try { field.set(object, translationValue); } catch (IllegalAccessException e) { throw new RuntimeException(e); }
                                }
                            }
                        }

                        //  获取子类集合的泛型
                        Class<?> subClazz = translationSupper.clazz();
                        if (subClazz != Void.class) {
                            //  判断field是否是集合类型，如果是则遍历集合进行翻译
                            if(field.getType().isAssignableFrom(List.class) || field.getType().isAssignableFrom(Set.class)) {
                                //  获取子类集合
                                List<?> subObjectList = ReflectUtils.invokeGetter(object, field.getName());
                                //  转换子类集合的泛型
                                subObjectList = JSON.parseArray(JSON.toJSONString(subObjectList), subClazz);

                                if (ObjectUtil.isNotNull(subObjectList) && !subObjectList.isEmpty()) {
                                    // 重新设置子类集合
                                    ReflectUtils.invokeSetter(object, field.getName(), subObjectList);

                                    List<CompletableFuture<Boolean>> subFutureList = new ArrayList<>();
                                    for (Object subObject : subObjectList) {
                                        translation(subObject, subFutureList);
                                    }

                                    //  等待子类异步线程结束
                                    for (CompletableFuture<Boolean> future : subFutureList) {
                                        CompletableFuture.allOf(future).join();
                                    }
                                }
                            }
                        }
                    }
                }

                return true;
            }));
        }
    }

}
